package com.wxxymaker.edu.service;

import com.blade.ioc.annotation.Bean;
import com.blade.ioc.annotation.Inject;
import com.blade.kit.CollectionKit;
import com.wxxymaker.edu.model.entity.Course;
import com.wxxymaker.edu.model.entity.LearnCourse;
import com.wxxymaker.edu.utils.TimeUtils;
import io.github.biezhi.anima.Anima;
import io.github.biezhi.anima.core.AnimaQuery;
import io.github.biezhi.anima.core.Joins;
import io.github.biezhi.anima.enums.OrderBy;
import io.github.biezhi.anima.page.Page;
import lombok.extern.slf4j.Slf4j;

/**
 * @AUTHOR soft
 * @DATE 2018/9/9 10:18
 * @DESCRIBE 加入学习业务
 */
@Bean
@Slf4j
public class LearnCourseService implements Service<LearnCourse> {

    @Inject
    private TaskService taskService;
    @Inject
    private LearnTaskService learnTaskService;

    /**
     * 更新学习进度
     * @param kid 课程id
     * @param uid 用户id
     */
    public boolean updateRate(int kid, int uid) {
        long total  = taskService.count(kid, true);
        long finish = learnTaskService.count(kid, uid, true);
        int  rate   = new Float(((float) finish) * 100 / total).intValue();
        return Anima.update().from(LearnCourse.class)
                .set(LearnCourse::getRate, rate)
                .set(LearnCourse::getFinish, finish)
                .where(LearnCourse::getCourseId, kid)
                .where(LearnCourse::getUserId, uid)
                .execute() > 0;
    }

    /**
     * 获取用户学习课程信息
     * 带上对应的课程
     * @param uid  用户id
     * @param over 是否学完 null全部 true学完 false没学完
     * @param page 页码
     * @param size 尺寸
     * @param join 是否加入课程实体
     */
    public Page<LearnCourse> page(Integer uid, Boolean over, int page, int size, boolean join) {
        AnimaQuery<LearnCourse> where = Anima.select().from(LearnCourse.class)
                .where(LearnCourse::getUserId, uid)
                .where(LearnCourse::getExist, 1)
                .order(LearnCourse::getEndUpdate, OrderBy.DESC);
        if (over != null) {
            if (over)
                where.where(LearnCourse::getRate).gte(100);
            else
                where.where(LearnCourse::getRate).lt(100);
        }
        if (join) {
            where.join(Joins.with(Course.class)
                    .as(LearnCourse::getCourse)
                    .on(LearnCourse::getCourseId, Course::getId));
        }
        Page<LearnCourse> page1 = where.page(page, size);
        if (CollectionKit.isNotEmpty(page1.getRows())) {
            for (LearnCourse learnCourse : page1.getRows()) {
                int kid = learnCourse.getCourseId();
                learnCourse.setTotalTask(taskService.count(kid, true));
                learnCourse.setNextTask(taskService.getNextTask(kid, uid, true));
            }
            return page1;
        }
        return null;
    }

    /**
     * 通过课程id和用户id获取学习信息
     * 包括下一节课 课程进度信息
     * @param kid 课程id
     * @param uid 用户id
     * @param jc 是否加入课程实体
     */
    public LearnCourse byKidAndUid(int kid, int uid, boolean jc) {
        AnimaQuery<LearnCourse> where = Anima.select().from(LearnCourse.class)
                .where(LearnCourse::getCourseId, kid)
                .where(LearnCourse::getExist, 1)
                .where(LearnCourse::getUserId, uid);
        if (jc) {
            where.join(Joins.with(Course.class)
                    .as(LearnCourse::getCourse)
                    .on(LearnCourse::getCourseId, Course::getId));
        }
        LearnCourse learnCourse = where.one();
        if (learnCourse != null) {
            learnCourse.setTotalTask(taskService.count(kid, true));
            learnCourse.setNextTask(taskService.getNextTask(kid, uid, true));
        }
        return learnCourse;
    }

    /**
     * 检测该课程是不是被加入学习
     * @param kid 课程id
     * @param uid 用户id
     */
    public boolean isJoin(int kid, int uid) {
        return Anima.select().from(LearnCourse.class)
                .where(LearnCourse::getCourseId, kid)
                .where(LearnCourse::getUserId, uid)
                .count() > 0;
    }

    /**
     * 加入学习
     * @param kid 课程id
     * @param uid 用户id
     */
    public LearnCourse join(int kid, int uid) {
        LearnCourse learnCourse = new LearnCourse();
        learnCourse.setUserId(uid);
        learnCourse.setCourseId(kid);
        learnCourse.setTime(TimeUtils.getTime());
        return this.add(learnCourse);
    }

    /**
     * 退出学习
     * @param kid 课程id
     * @param uid 用户id
     */
    public boolean unjoin(int kid, int uid) {
        if (Anima.delete().from(LearnCourse.class)
                .where(LearnCourse::getUserId, uid)
                .where(LearnCourse::getCourseId, kid)
                .execute() > 0) {
            learnTaskService.unjoin(kid, uid);
            return true;
        }
        return false;
    }

    /**
     * 通过课程id取消该课程下的所有加入学习 取消课程发布时使用
     * @param kid 课程id
     */
    public boolean unJoins(int kid) {
        if (Anima.update().from(LearnCourse.class)
                .set(LearnCourse::getExist, 0)
                .where(LearnCourse::getCourseId, kid)
                .execute() > 0) {
            learnTaskService.deleteByKid(kid);
            return true;
        }
        return false;
    }

    /**
     * 添加
     */
    @Override
    public LearnCourse add(LearnCourse learnCourse) {
        learnCourse.setExist(1);
        boolean rollback = Anima.atomic(() -> {
            learnCourse.setTime(TimeUtils.getTime());
            learnCourse.setId(learnCourse.save().asInt());
        }).catchException(e -> {
            log.error("添加失败！{}", e.getMessage());
        }).isRollback();
        return rollback ? null : learnCourse;
    }

    @Override
    public LearnCourse delete(Object pk) {
        LearnCourse learnCourse = byId(pk);
        boolean rollback = Anima.atomic(learnCourse::delete)
        .catchException(e -> {
            log.error("删除失败！{}", e.getMessage());
        }).isRollback();
        return rollback ? null : learnCourse;
    }

    @Override
    public boolean change(LearnCourse learnCourse) {
        boolean rollback = Anima.atomic(learnCourse::update)
        .catchException(e -> {
            log.error("修改失败！{}", e.getMessage());
        }).isRollback();
        return !rollback;
    }

    @Override
    public LearnCourse byId(Object pk) {
        return Anima.select().from(LearnCourse.class)
                .where(LearnCourse::getExist, 1)
                .byId(pk);
    }

    public Long countByUid(Integer userId) {
        return Anima.select().from(LearnCourse.class)
                .where(LearnCourse::getUserId, userId)
                .count();
    }
}
